//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;

namespace OpenLS.Spreadsheet
{
    partial class Workbook
    {
        
        internal enum CalcualtionDisablerMode
        {
            Loading,
            Other
        }
         class CalculationDisabler : IDisposable
        {
            private readonly Workbook workbook;

            public CalculationDisabler(Workbook workbook, CalcualtionDisablerMode mode)
            {
                Contract.Requires(workbook != null);
                Contract.Requires(workbook._calculationDisabler == null);
                this.workbook = workbook;
                this._mode = mode;
                
                workbook._calculationDisabler = this;
            }

            readonly HashListNoDuplicate<Cell> modifiedCells = new HashListNoDuplicate<Cell>();
             private CalcualtionDisablerMode _mode;

             public void Add(Cell cell)
            {
                if (_mode == CalcualtionDisablerMode.Loading)
                    return;
                if (!modifiedCells.Contains(cell))
                    modifiedCells.Add(cell);
            }
            #region IDisposable Members

            void IDisposable.Dispose()
            {

                var chain = new CalculationChain(GetNodes());
                chain.Calculate();
                workbook._calculationDisabler = null;
            }
            IEnumerable<IDependencyNode> GetNodes()
            {
                foreach (Cell node in modifiedCells)
                    yield return node;
            }

            #endregion
        }

        internal void CalculateCell(Cell cell)
        {
            var modifiedCells = _calculationDisabler;
            if (modifiedCells != null)
            {
                modifiedCells.Add(cell);
                return;
            }
            var chain = new CalculationChain(cell);
            chain.Calculate();

        }
        CalculationDisabler _calculationDisabler;
        /// <summary>
        /// Create an object which disables calculation. When this object is disposed, all modified cells are calculated.
        /// </summary>
        /// <returns></returns>
        public IDisposable CreateCalculationDisabler()
        {
            return new CalculationDisabler(this, CalcualtionDisablerMode.Other);
        }
        internal IDisposable CreateLoadingCalculationDisabler()
        {
            return new CalculationDisabler(this, CalcualtionDisablerMode.Loading);
        }

        internal enum CalculationDisablerMode
        {
            Loading,
            Other
        }
    }
}
